<script lang="ts" setup>
import type { FormInstance, UploadProps } from 'ant-design-vue'
import { message } from 'ant-design-vue'
import { UploadOutlined } from '@ant-design/icons-vue'
import { computed, reactive, ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useI18n } from 'vue-i18n'
import type { Cluster } from '@/api'
import { api } from '@/api'
import type { DistributionParams } from '@/api/paths/types'
import { useClusterStore, useRepoStore } from '@/store'

defineProps<{
  visible: boolean
}>()

const emits = defineEmits<{
  (e: 'update:visible', status: boolean): void
}>()

const { t } = useI18n()

const { permissions } = storeToRefs(useClusterStore())

const clusters = computed<Cluster[]>(() => permissions.value.map(i => ({ cluster_name: i.cluster_name, cluster_id: i.cluster_id })))

const formRef = ref<FormInstance>()
const form = reactive({
  cluster_id: undefined,
  repo_name: '',
  repo_data: '',
})

const fileList = ref<UploadProps['fileList']>([])

async function handleSubmit() {
  try {
    await formRef.value!.validate()
    const params: DistributionParams<{ repo_name: string, repo_data: string }> = {}
    const { cluster_id, repo_data, repo_name } = form
    params[cluster_id!] = {
      repo_name,
      repo_data,
    }
    const [_] = await api.createNewRepo(params)
    if (!_) {
      message.success(t('common.succeed'))
      formRef.value?.resetFields()
      fileList.value = []
      emits('update:visible', false)
      const { queryRepos } = useRepoStore()
      await queryRepos()
    }
  }
  catch {
  }
}

function handleCancel() {
  formRef.value?.resetFields()
  fileList.value = []
  emits('update:visible', false)
}

const removeFile: UploadProps['onRemove'] = (file) => {
  if (!fileList.value)
    return
  const index = fileList.value.indexOf(file)
  const newFileList = fileList.value.slice()
  newFileList.splice(index, 1)
  fileList.value = newFileList
}

function arrayBufferToString(buffer) {
  const decoder = new TextDecoder('utf-8')
  return decoder.decode(buffer)
}

/**
 * read file as array buffer
 * @param file
 */
async function readFile(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = event => resolve(arrayBufferToString(event.target!.result))
    reader.onerror = reject
    reader.readAsArrayBuffer(file)
  })
}

const beforeUpload: UploadProps['beforeUpload'] = async (file) => {
  fileList.value = []
  const fileData = await readFile(file)
  if (fileData)
    form.repo_data = fileData
  return false
}

async function handleDownLoad() {
  const [_] = await api.downLoadRepoTemplate()
  if (_)
    message.error(t('common.downloadFail'))
}
</script>

<template>
  <a-modal
    :title="$t('vul.repo.newRepo')"
    :open="visible"
    destroy-on-close
    @cancel="handleCancel"
    @ok="handleSubmit"
  >
    <a-form ref="formRef" :model="form" :label-col="{ span: 6 }" :wrapper-col="{ span: 19 }">
      <a-form-item
        name="cluster_id"
        :label="$t('vul.cluster')"
        :rules="[{ required: true, message: $t('assests.placeHolder.cluster') }]"
      >
        <a-select v-model:value="form.cluster_id" :placeholder="$t('assests.placeHolder.cluster')">
          <template v-for="cluster in clusters" :key="cluster.cluster_id">
            <a-select-option :value="cluster.cluster_id">
              {{
                cluster.cluster_name
              }}
            </a-select-option>
          </template>
        </a-select>
      </a-form-item>

      <a-form-item
        name="repo_name"
        :label="$t('vul.repo.repoName')"
        :rules="[
          { required: true, message: $t('vul.repo.placeHolder.repoContent') },
          { max: 20, message: '20个字符以内' },
        ]"
      >
        <a-input v-model:value="form.repo_name" :placeholder="$t('vul.repo.placeHolder.repoContent')" />
      </a-form-item>

      <a-form-item
        name="repo_data"
        :rules="[{ required: true, message: $t('vul.repo.placeHolder.repoDesc') }]"
      >
        <template #label>
          <div>{{ $t('vul.repo.repoContent') }}</div>
          <a-button size="small" class="button" @click="handleDownLoad">
            {{ $t('common.downloadTemp') }}
          </a-button>
        </template>
        <a-textarea
          v-model:value="form.repo_data"
          :placeholder="$t('vul.repo.placeHolder.repoDesc')"
          :rows="10"
        />
      </a-form-item>

      <a-form-item :label="$t('common.ImportFile')">
        <a-upload
          v-model:file-list="fileList"
          name="file"
          :before-upload="beforeUpload"
          @remove="removeFile"
        >
          <a-button>
            <UploadOutlined />
            {{ $t('common.selectDoc') }}
          </a-button>
        </a-upload>
      </a-form-item>
    </a-form>
  </a-modal>
</template>

<style scoped>
.button {
  position: absolute;
  left: 0;
  top: 30px;
}
</style>
